﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Common;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Factories;
using FarseerPhysics;

namespace chemicall
{
    public enum ScreenState
    {
        TransitionOn,
        Active,
        TransitionOff,
        Hidden,
    }

    public abstract class GameScreen 
    {
        
        public GraphicsDeviceManager graphics;
        public SpriteBatch spriteBatch;
        //par défaut sera pas une fenêtre popUp mais j'ai pensé que peut être pour 
        //donner la description de H2O ou CO2 on pourrait faire une fenêtre popUp
        bool isPopup = false; 
        TimeSpan transitionOnTime = TimeSpan.Zero;
        TimeSpan transitionOffTime = TimeSpan.Zero;
        float transitionPosition = 1;
        public ScreenState screenState = ScreenState.TransitionOn;
        bool isExiting = false;
        bool otherScreenHasFocus;
        PlayerIndex? controllingPlayer;
        bool isSerializable = true;
        public SpriteFont _classicFont;
        public ContentManager content;
        public SimulatePause myPause;

        public ScreenManager ScreenManager
        {
            get { return screenManager; }
            internal set { screenManager = value; }
        }

        ScreenManager screenManager;

        public bool IsPopup
        {
            get { return isPopup; }
            protected set { isPopup = value; }
        }

        //Le temmps de transition d'une fenêtre à autre quand la fenêtre est active
        public TimeSpan TransitionOnTime
        {
            get { return transitionOnTime; }
            protected set { transitionOnTime = value; }
        }

        //quand la fenêtre n'est pas active
        public TimeSpan TransitionOffTime
        {
            get { return transitionOffTime; }
            protected set { transitionOffTime = value; }
        }

        //L'etat de la transition 0 = active, pas de transition. 1 transition completé
        public float TransitionPosition
        {
            get { return transitionPosition; }
            protected set { transitionPosition = value; }
        }

        public float TransitionAlpha
        {
            get { return 1f - TransitionPosition; }
        }

        //état de la transition de l'autre fenêtre
        public ScreenState ScreenState
        {
            get { return screenState; }
            protected set { screenState = value; }
        }

        //savoir si la fenêtre va pas être reutilisé pour l'eliminer 
        public bool IsExiting
        {
            get { return isExiting; }
            protected internal set { isExiting = value; }
        }

        public bool IsActive
        {
            get
            {
                return !otherScreenHasFocus &&
                       (screenState == ScreenState.TransitionOn ||
                        screenState == ScreenState.Active);
            }
        }

        public PlayerIndex? ControllingPlayer
        {
            get { return controllingPlayer; }
            internal set { controllingPlayer = value; }
        }

        public bool IsSerializable
        {
            get { return isSerializable; }
            protected set { isSerializable = value; }
        }

        public virtual void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
        {
            this.otherScreenHasFocus = otherScreenHasFocus;

            if (isExiting)
            {
                screenState = ScreenState.TransitionOff;
            }
            else if (coveredByOtherScreen)
            {
                if (UpdateTransition(gameTime, transitionOffTime, 1))
                {
                    screenState = ScreenState.TransitionOff;
                }
                else
                {
                    screenState = ScreenState.Hidden;
                }
            }
            else
            {
                if (UpdateTransition(gameTime, transitionOnTime, -1))
                {
                    screenState = ScreenState.TransitionOn;
                }
                else
                {
                    screenState = ScreenState.Active;
                }
            }
            if (myPause != null)
                myPause.Update(gameTime);
        }

        bool UpdateTransition(GameTime gameTime, TimeSpan time, int direction)
        {
            float transitionDelta;

            if (time == TimeSpan.Zero)
                transitionDelta = 1;
            else
                transitionDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / time.TotalMilliseconds);

            transitionPosition += transitionDelta * direction;

            if (((direction < 0) && (transitionPosition <= 0)) ||
                ((direction > 0) && (transitionPosition >= 1)))
            {
                transitionPosition = MathHelper.Clamp(transitionPosition, 0, 1);
                return false;
            }

            return true;
        }

        public virtual void Draw(GameTime gameTime) { }
        public virtual void Activate(bool instancePreserved) { }
        
        public virtual void HandleInput(GameTime gameTime, KeyboardState states) 
        { 
            if (states.IsKeyDown(Keys.Escape) && myPause != null)
            {
                if (!myPause.Paused)
                {
                    myPause.Paused = true;
                    screenManager.AddScreen(new PauseMenu(), PlayerIndex.One);
                }
                else
                    myPause.Paused = false;
            }
        }

        public void ExitScreen()
        {
                isExiting = true;
        }
    }
}
